<template>
  <view
    class="tn-count-to"
    :class="[countToClass]"
    :style="countToStyle"
  >
    {{ displayValue }}
  </view>
</template>

<script lang="ts" setup>
import { countToProps, countToEmits, CountToSeparator } from '../../../types/tn-count-to'
import useCountTo from '../lib/hooks/useCountTo'
import { computed, watch, CSSProperties, onMounted, onBeforeUnmount, nextTick } from 'vue'
import useComponentColor from '../../../libs/hooks/useComponentColor'
import { handleValueWithUnit } from '../../../utils'

const props = defineProps(countToProps)
const emits = defineEmits(countToEmits)

const { generateColorInfo } = useComponentColor()
let componentColorInfo = generateColorInfo(props?.color || '')
// 监听颜色变化实时修改颜色对应的属性
watch(() => props.color, (nVal) => {
  componentColorInfo = generateColorInfo(nVal)
})

// 分隔符配置
const separatorOption = computed<CountToSeparator>(() => {
  return Object.assign({
    decimal: '.',
    thousandths: ''
  }, props?.separatorOption || {})
})

// countTo样式
const countToStyle = computed<CSSProperties>(() => {
  let style: CSSProperties = {}
  if (componentColorInfo.style?.color) style.color = componentColorInfo.style.color
  if (props?.fontSize) style.fontSize = handleValueWithUnit(props.fontSize)
  return style
})

// countTo对应的类
const countToClass = computed<string>(() => {
  let clazz: string[] = []
  if (componentColorInfo.class.length > 0) clazz.push(...componentColorInfo.class)
  if (props?.bold) clazz.push('tn-text-bold')
  return clazz.join(' ')
})

// 动画结束回调函数
const countToEnd = () => {
  emits('end')
}
const { displayValue, updateValue, updateOption, startAnimation, pauseAnimation, resumeAnimation } = useCountTo(countToEnd)
watch(() => {
  return [props.startValue, props.endValue]
}, () => {
  updateValue(
    Number(props?.startValue) || 0,
    Number(props?.endValue) || 0,
    props?.autoplay)
})
onMounted(() => {
  nextTick(() => {
    updateOption(
      separatorOption.value,
      Number(props?.decimals) || 0,
      Number(props?.duration) || 200)
    updateValue(
      Number(props?.startValue) || 0,
      Number(props?.endValue) || 0,
      props?.autoplay)
  })
})

onBeforeUnmount(() => {
  pauseAnimation()
})

// 对外提供的接口
const start = () => {
  updateValue(
    Number(props?.startValue) || 0,
    Number(props?.endValue) || 0)
  startAnimation()
}
const paused = () => {
  pauseAnimation()
}
const resume = () => {
  resumeAnimation()
}

defineExpose({
  start,
  paused,
  resume
})
</script>

<script lang="ts">
export default {
  options: {
    // 在微信小程序中将组件节点渲染为虚拟节点，更加接近Vue组件的表现(不会出现shadow节点下再去创建元素)
    virtualHost: true
  }
}
</script>

<style lang="scss" scoped>
.tn-count-to {
  display: inline-block;
  line-height: 1;
  font-size: 40rpx;
}
</style>
